package UIFree.controls
{
	import UIFree.ObjectEvent;
	import UIFree.uif_Timer;
	import UIFree.uif_component;
	import UIFree.uif_ecomponent;
	
	import UIUtils.uif_util;
	
	import flash.display.DisplayObject;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.events.TimerEvent;
	import flash.geom.Rectangle;
	import flash.utils.Timer;

	public class uif_popupMenu extends uif_vaScrollArea {
		private var _activeControl	: uif_ecomponent;
		private var _listLayer		: uif_ecomponent;
		private var _options		: Object;
		private var _waitTimer		: Timer;
		protected static var _curShowMenu	: uif_popupMenu;
		
		public static var DEFAUITEMHEIGHT		: int = 23;
		public static var ITEMSTYLEFIELD		: String = 'item';
		public static var DEFAULTCAPTIONFIELD	: String = 'caption';
		public static var DEFAULTSHORTKEYFIELD	: String = 'shortkeys';
		public static var DEFAULTHINTFIELD		: String = 'hint';
		public static var SUBMENUFIELD			: String = 'submenu';
		public static var TOPPOSITION			: int = 1;				
		public static var RIGHTPOSITION			: int = 2;				
		public static var BOTTOMPOSITION		: int = 3;				
		public static var LEFTPOSITION			: int = 4;
		public static var WAITHIDETIME			: int = 200;
		
		public function uif_popupMenu(parent: uif_component, options: Object, a_width: int=0, a_height: int=0,
									styleClass: String='') {
			super(parent, 0, 0, a_width, a_height, styleClass);
			_options = uif_util.union({
				itemClass	: uif_label,
				showEvent	: MouseEvent.MOUSE_DOWN,
				parentMenu	: null
			}, options);
			
			alpha = 0;
			visible = false;
			
			_waitTimer = new Timer(WAITHIDETIME, 1);
			_waitTimer.addEventListener(TimerEvent.TIMER_COMPLETE, doWaitTimer);
		}
		
		override protected function listenEvents(): void {
			addEvent(MouseEvent.CLICK, function(e: MouseEvent): void {
				if (visible && _activeControl && (!_activeControl.contains(e.target as DisplayObject))) doHideMenu(e);
			}, stage);
		}
		
		public function set activeControl(control: uif_ecomponent): void {
			if (control != _activeControl) doActiveControl(control);
		}
		
		public function get activeControl(): uif_ecomponent {
			return _activeControl;
		}
		
		protected function detachActiveControl(): void {
			if (_activeControl) {
				_activeControl.removeEventListener(uif_ecomponent.DISPOSE, doControlDispose);
				_activeControl.removeEventListener(uif_component.POSITION, doControlPosition);
				_activeControl.removeEventListener(_options.showEvent, doControlFocus);
				if (_options.showEvent == MouseEvent.ROLL_OVER) {
					 _activeControl.removeEventListener(MouseEvent.ROLL_OUT, doControlUnfocus);
					 removeEventListener(MouseEvent.ROLL_OUT, doControlUnfocus);
					 removeEventListener(MouseEvent.ROLL_OVER, doClearWaitTimer);
				}
			}
		}
		
		protected function doActiveControl(control: uif_ecomponent): void {
			detachActiveControl();
			_activeControl = control;
			if (_activeControl) {
				_activeControl.addEvent(uif_ecomponent.DISPOSE, doControlDispose);
				_activeControl.addEvent(uif_component.POSITION, doControlPosition);
				_activeControl.addEvent(_options.showEvent, doControlFocus);
				if (_options.showEvent == MouseEvent.ROLL_OVER) {
					 _activeControl.addEvent(MouseEvent.ROLL_OUT, doControlUnfocus);
					 addEvent(MouseEvent.ROLL_OUT, doControlUnfocus);
					 addEvent(MouseEvent.ROLL_OVER, doRollOver);
				}
				
				if (_activeControl.hitMouse) showMenu();
			}
		}
		
		private function doControlPosition(e: Event): void {
			if (visible) updateMenuPosition();
		}
		
		private function doControlDispose(e: Event): void {
			detachActiveControl();
			hideMenu();
		}
		
		protected function doWaitTimer(e: TimerEvent=null): void {
			if (!hitMouse) hideMenu();
		}
		
		protected function doControlUnfocus(me: Event): void {
			doUnfocus();
		}
		
		protected function doRollOver(e: Event): void {
			doFocus();
		}
		
		protected function doUnfocus(waitFocus: Boolean=true): void {
			if (!waitFocus) doWaitTimer()
			else if (!_waitTimer.running) _waitTimer.start();
			if (_options.parentMenu) _options.parentMenu.doUnfocus();
		}
		
		protected function doFocus(): void {
			doClearWaitTimer();	
			if (_options.parentMenu)
				_options.parentMenu.doFocus();
		}
		
		protected function doClearWaitTimer(): void {
			if (_waitTimer.running) {
				_waitTimer.stop();
			} else if (alpha < 1) {
				FXNameCancel('alpha');
				alpha = 1;
			}
		} 
		
		protected function doHideMenu(e: MouseEvent): void {
			hideMenu();
		}
		
		public function get listMenu(): Array {
			return this.list;
		} 
		
		public function set listMenu(a_list: Array): void {
			if (a_list != this.list) doListMenu(a_list);
		}
		
		protected function doListMenu(a_list: Array): void {
			clearList();
			var space: Number = getSpace() + app.getStyleSpace(style[ITEMSTYLEFIELD]);
			var v_width: int = maxWidthList(a_list) + space * 2;
			if (v_width < width) v_width = width; 
			resize(v_width, (a_list)?(a_list.length * menuItemHeight + getSpace() * 2):0);
			this.attachList(a_list, doElemCreate);
		}
		
		public function clearList(): void {
			if (listMenu) listMenu.splice(0);
			area.disposeChilds();
		}
		
		protected function doControlFocus(e: MouseEvent): void {
			if (!e.buttonDown && _activeControl && !_activeControl.disable) 
				showIfNotNull();
		}
		
		public function showIfNotNull(): void {
			if (!empty)
				uif_Timer.one(500, function(e: Event): void {showIfHit()});
		}
		
		public function showIfHit(): void {
			if (_activeControl.hitMouse) showMenu();
		}

		protected function maxWidthList(a_list: Array): int {
			var itStyle: Object = app.styleByName(style[ITEMSTYLEFIELD]);
			return uif_component.maxWidth(uif_util.values(a_list, DEFAULTCAPTIONFIELD), 
									itStyle.text_format.font, itStyle.text_format.size) +
					uif_component.maxWidth(uif_util.values(a_list, DEFAULTSHORTKEYFIELD), 
						itStyle.text_format.font, itStyle.text_format.size) +
						app.getStyleSpace(itStyle, true) * 2;
		}
		
		protected function doItemClick(e: MouseEvent): void {
			var tpm: uif_popupMenu = getTopParentMenu();
			(tpm?tpm:this).dispatchEvent(new ObjectEvent(Event.SELECT, e.target._data));
		}
		
		protected function getTopParentMenu(): uif_popupMenu {
			var parentMenu: uif_popupMenu = _options.parentMenu;
			while (parentMenu) {
				if (!parentMenu._options.parentMenu) break;
				parentMenu = parentMenu._options.parentMenu;
			}
			return parentMenu;
		}
		
		public function showMenu(): void {
			if (!disable) {
				updateMenuPosition();
				slideShow();
				
				if (!_options.parentMenu) { 
					if (_curShowMenu && (_curShowMenu != this)) {
						_curShowMenu.hideMenu();
					}
					
					_curShowMenu = this;
				}
				
				if (_waitTimer.running)
					_waitTimer.stop();
			}
		}
		
		protected function updateMenuPosition(): void {
			if (_activeControl) {
				var bounds: Rectangle = _activeControl.getBounds(stage);
				bounds.topLeft 		= parent.globalToLocal(bounds.topLeft);
				bounds.bottomRight 	= parent.globalToLocal(bounds.bottomRight);
				var rect: Rectangle = getOuter();
				if (!_options.orientation || (_options.orientation == BOTTOMPOSITION)) {
					rect.x = bounds.x;
					rect.y = bounds.y + bounds.height;
				} else if (_options.orientation == TOPPOSITION) {
					rect.x = bounds.x;
					rect.y = bounds.y - height;
				} else if (_options.orientation == LEFTPOSITION) {
					rect.x = bounds.x - width;
					rect.y = bounds.y;
				} else if (_options.orientation == RIGHTPOSITION) {
					rect.x = bounds.x + bounds.width;
					rect.y = bounds.y;
				}
				
				position = uif_util.correctPosition(parentComponent.getInner(), rect).topLeft;
			}
		}
		
		public function hideMenu(): void {
			slideHide(function(): void {
				if (_curShowMenu == This) _curShowMenu = null;
			});
		}   
		
		protected function get menuItemHeight(): Number {
			return style.menuItemHeight?style.menuItemHeight:DEFAUITEMHEIGHT;
		}
		
		protected function createSubmenu(item: uif_label, submenuList: Array): void {
			var _menu: uif_popupMenu = new uif_popupMenu(parentComponent, {
				orientation	: uif_popupMenu.RIGHTPOSITION,
				itemClass	: _options.itemClass,
				showEvent	: _options.showEvent,
				parentMenu	: this
			}, 100, 100, styleClass);
			
			_menu.listMenu = submenuList;
			_menu.activeControl = item;			
		}
		
		protected function doElemCreate(_area: uif_ecomponent, item: Object, index: int): uif_ecomponent {
			var inner: Rectangle = getInner();
			var l_item: uif_label = new (item.itemClass?item.itemClass:_options.itemClass)(_area, inner.x, inner.y + index * menuItemHeight, inner.width, menuItemHeight, style[ITEMSTYLEFIELD]);
			l_item.text = item[DEFAULTCAPTIONFIELD];
			if (item[DEFAULTHINTFIELD]) l_item.hint = item[DEFAULTHINTFIELD];
			l_item.addEvent(MouseEvent.CLICK, doItemClick);
			
			if (item[SUBMENUFIELD]) createSubmenu(l_item, item[SUBMENUFIELD]);
			return l_item;
		}
	}
}